home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / wgt / wgttut4 / animate2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-28  |  6.8 KB  |  287 lines

  1. #include <dos.h>
  2. #include <wgt4.h>
  3. #include <stdlib.h>
  4. #include <conio.h>
  5.  
  6. /* WGT Tutorial #4
  7.    Example Program 2.
  8.  
  9.    This example shows the easiest method of animation.  It requires two
  10.    320x200 screens.  The first contains the background image which never
  11.    changes.  The second is a work screen, where the sprites will be
  12.    drawn.
  13.  
  14.    The animation loop is very simple.  First, copy the background screen
  15.    to the work screen.  This erases the previous sprites in a brute force
  16.    method.  All the sprites are drawn on the work screen with an xray copy.
  17.    The work screen is copied to the visual screen, and the this process
  18.    is repeated. */
  19.  
  20. block sprite_images[30];        /* Holds the images for our sprites */
  21. color pal[256];                 /* The palette */
  22.  
  23. block backgroundscreen;         /* Holds the background image */
  24. block workscreen;               /* Holds work screen */
  25.  
  26. #define NUM_SPRITES 10          /* Maximum number of sprites */
  27.  
  28. #define SPEED 4                 /* Speed and direction of the sprites.
  29.                    Negative speeds mean up and left. */
  30.  
  31.  
  32. /* Our sprite structure */
  33. typedef struct
  34.  {
  35.   int x, y;             /* Coordinate on the screen */
  36.   int num;              /* Index into the sprite_image array of blocks */
  37.   int dx, dy;           /* speed in the x and y direction */
  38.   int width, height;    /* Width and height of the sprite's image */
  39.  
  40.   int ox, oy, ox2, oy2;
  41.  } sprite;
  42.  
  43. int rx, ry, rx2, ry2;
  44.  
  45. sprite objects[NUM_SPRITES];    /* an array of sprites */
  46.  
  47.  
  48.  
  49. void load_graphics (void)
  50. /* Load the sprites and make our background and work screens. */
  51. {
  52. int i;
  53.  
  54.  wloadsprites (pal, "anim.spr", sprite_images, 0, 29);
  55.  wsetpalette (0, 255, pal);
  56.  
  57.  backgroundscreen = wloadpcx256 ("lunar.pcx", pal);
  58.  wputblock (0, 0, backgroundscreen, 0);
  59.  workscreen = wnewblock (0, 0, 319, 199);
  60. }
  61.  
  62.  
  63. void free_graphics (void)
  64. /* Frees the sprite images and the screens */
  65. {
  66.  wfreesprites (sprite_images, 0, 29);
  67.  wfreeblock (workscreen);
  68.  wfreeblock (backgroundscreen);
  69. }
  70.  
  71.  
  72. void initialize_sprites (void)
  73. /* Set up the initial values in the sprite array */
  74. {
  75. int i;
  76. sprite *spriteptr;
  77.  
  78.  spriteptr = objects;
  79.  for (i = 0; i < NUM_SPRITES; i++)
  80.   {
  81.    spriteptr->num = 0;
  82.    /* Image number 0 */
  83.  
  84.    spriteptr->width = wgetblockwidth (sprite_images[spriteptr->num]);
  85.    spriteptr->height = wgetblockheight (sprite_images[spriteptr->num]);
  86.    /* width and height are the size of the image # num */
  87.  
  88.    spriteptr->x = rand () % 320 - spriteptr->width;
  89.    spriteptr->y = rand () % 200 - spriteptr->height;
  90.    /* Pick a random coordinate */
  91.  
  92.    spriteptr->dx = SPEED;
  93.    spriteptr->dy = SPEED;
  94.    /* Moving down and right */
  95.  
  96.    spriteptr->ox = spriteptr->x;
  97.    spriteptr->oy = spriteptr->y;
  98.    spriteptr->ox2 = spriteptr->x + spriteptr->width - 1;
  99.    spriteptr->oy2 = spriteptr->y + spriteptr->height - 1;
  100.  
  101.    spriteptr++; /* Next sprite */
  102.   }
  103. }
  104.  
  105.  
  106.  
  107.  
  108. void erase_sprites (void)
  109. /* Erases each sprite by copying the section from the background screen. */
  110. {
  111. int i;
  112. sprite *spriteptr;
  113.  
  114. int x, y, x2, y2;
  115.  
  116.  
  117.   wsetscreen (workscreen);
  118.  
  119.   spriteptr = objects;
  120.  
  121.   for (i = 0; i < NUM_SPRITES; i++)
  122.    {
  123.     x = spriteptr->ox;          /* Get the old dirty rectangle coordinates */
  124.     y = spriteptr->oy;
  125.     x2 = spriteptr->ox2;
  126.     y2 = spriteptr->oy2;
  127.  
  128.     if (x < 0)                  /* Clip them, but don't change the original */
  129.     x = 0;                  /* values, because we need them later */
  130.     else if (x > 319)
  131.     x = 319;
  132.     if (y < 0)
  133.     y = 0;
  134.     else if (y > 199)
  135.     y = 199;
  136.  
  137.     wcopyscreen (x, y, x2, y2, backgroundscreen, x, y, workscreen);
  138.  
  139.     spriteptr++;   /* Next sprite */
  140.    }
  141. }
  142.  
  143.  
  144. void expand_dirty_rectangle (int sprite_num, int x, int y, int x2, int y2)
  145. /* Find boundaries of the old and new sprite rectangle */
  146. {
  147. sprite *spriteptr;
  148.  
  149.  spriteptr = &objects[sprite_num];
  150.  
  151.  if (x < rx)
  152.      rx = x;
  153.  if (x2 > rx2)
  154.      rx2 = x2;
  155.  if (y < ry)
  156.      ry = y;
  157.  if (y2 > ry2)
  158.      ry2 = y2;
  159.  
  160.  
  161.   if (rx < 0)
  162.       rx = 0;
  163.  
  164.   if (rx2 > 319)
  165.       rx2 = 319;
  166.  
  167.   if (ry < 0)
  168.       ry = 0;
  169.  
  170.   if (ry2 > 199)
  171.       ry2 = 199;
  172. }
  173.  
  174.  
  175.  
  176. void draw_and_move_sprites (void)
  177. /* Moves each sprite based on the speed and direction, and bounces them
  178.   off the side of the screen if needed.  It then draws the sprite on the
  179.   work screen.   Sprites are drawn from lowest to highest, meaning the
  180.   higher numbered sprites will be above the rest. */
  181. {
  182. int i;
  183. sprite *spriteptr;
  184.  
  185.   wsetscreen (workscreen);
  186.  
  187.   spriteptr = objects;
  188.  
  189.   for (i = 0; i < NUM_SPRITES; i++)
  190.    {
  191.     spriteptr->num++;           /* Animate the sprite through images 0-29 */
  192.     if (spriteptr->num > 29)
  193.        spriteptr->num = 0;
  194.  
  195.     /* Since we changed sprites, we need to get the new width and height
  196.        of the image.  Only do this when you change spriteptr->num. */
  197.     spriteptr->width = wgetblockwidth (sprite_images[spriteptr->num]);
  198.     spriteptr->height = wgetblockheight (sprite_images[spriteptr->num]);
  199.  
  200.     spriteptr->x += spriteptr->dx;
  201.     spriteptr->y += spriteptr->dy;
  202.     /* Add the speed/direction to the current coordinate */
  203.  
  204.     if (spriteptr->x > 319 - spriteptr->width)
  205.       spriteptr->dx = -SPEED;
  206.     else if (spriteptr->x < 0)
  207.       spriteptr->dx = SPEED;
  208.     /* Change the direction horizontally if needed */
  209.  
  210.     if (spriteptr->y > 199 - spriteptr->height)
  211.       spriteptr->dy = -SPEED;
  212.     else if (spriteptr->y < 0)
  213.       spriteptr->dy = SPEED;
  214.     /* Change the direction vertically if needed */
  215.  
  216.     wputblock (spriteptr->x, spriteptr->y, sprite_images[spriteptr->num], 1);
  217.     /* Draw the sprite with xray copy */
  218.  
  219.     spriteptr++;   /* Next sprite */
  220.    }
  221. }
  222.  
  223.  
  224. void copy_sprites (void)
  225. {
  226. int i;
  227. sprite *spriteptr;
  228. int x, y, x2, y2;
  229.  
  230.   spriteptr = objects;
  231.   for (i = 0; i < NUM_SPRITES; i++)
  232.    {
  233.     /* Store these values because they are used more than once */
  234.     x  = spriteptr->x;
  235.     y  = spriteptr->y;
  236.     x2 = spriteptr->x + spriteptr->width - 1;
  237.     y2 = spriteptr->y + spriteptr->height - 1;
  238.  
  239.     /* Set the dirty rectangle to the current position of the sprite */
  240.     rx  = x;
  241.     ry  = y;
  242.     rx2 = x2;
  243.     ry2 = y2;
  244.  
  245.     expand_dirty_rectangle (i, spriteptr->ox, spriteptr->oy,
  246.                    spriteptr->ox2, spriteptr->oy2);
  247.  
  248.     wcopyscreen (rx, ry, rx2, ry2, workscreen, rx, ry, NULL);
  249.  
  250.     spriteptr->ox = x;
  251.     spriteptr->oy = y;
  252.     spriteptr->ox2 = x2;
  253.     spriteptr->oy2 = y2;
  254.  
  255.     spriteptr++;
  256.  
  257.    }
  258. }
  259.  
  260.  
  261.  
  262. void main (void)
  263. {
  264.  vga256 ();
  265.  
  266.  load_graphics ();
  267.  
  268.  initialize_sprites ();
  269.  
  270.  do {
  271.  
  272.   erase_sprites ();
  273.   /* Erase the previous frame from the work screen */
  274.  
  275.   draw_and_move_sprites ();
  276.   /* Draw the sprites overtop the work screen */
  277.  
  278.   //wretrace ();
  279.   copy_sprites ();
  280.  
  281.  } while (!kbhit ());
  282.  
  283.  
  284.  free_graphics ();
  285.  wsetmode (3);
  286. }
  287.